/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package app;

import java.awt.*;

/**
 *
 * @author CygiDawid
 */
public class LineFunction implements java.io.Serializable {
    private final Point _start;
    private final Point _end;
    private final double _a;
    private final double _b;
    private double _calc;
    private boolean _vert = false;
    private int _minX;
    private int _maxX;
    private int _minY;
    private int _maxY;
    
    
    public LineFunction(Point start, Point end) {
        _start = start;
        _end = end;
        
        setExtremums();
        
        _a = (_start.y - _end.y) / (double)(_start.x - _end.x);
        if (Double.isInfinite(_a)) {
            _b = 0;
            _vert = true;
            return;
        }
        
        _b = _start.y - _a * _start.x;
        _calc = 1d / Math.sqrt(_a * _a + 1d);
    }
    
    
    private void setExtremums() {
        if (_start.x < _end.x) {
            _minX = _start.x;
            _maxX = _end.x;
        }
        else {
            _minX = _end.x;
            _maxX = _start.x;
        }
        
        if (_start.y < _end.y) {
            _minY = _start.y;
            _maxY = _end.y;
        }
        else {
            _minY = _end.y;
            _maxY = _start.y;
        }
    }
    
    public double getA() {
        return _a;
    }
    
    public double getB() {
        return _b;
    }
    
    public Point getStart() {
        return _start;
    }
    
    public Point getEnd() {
        return _end;
    }
    
    public Point[] getEx() {
        return new Point[] { new Point(_minX,_minY), new Point(_maxX,_maxY) };
    }
    
    
    public boolean isOn(Point point) {
        return ((point.x >= _minX && point.x <= _maxX) &&
                (point.y >= _minY && point.y <= _maxY));
    }
    
    public double getDistFromLine(Point point) {
        if (_vert) {
            return Math.abs(_start.x - point.x);
        }
        else {
            return Math.abs(_a * point.x - point.y + _b) * _calc;
        }
    }
    
    public static Point[] getDistPoints(double a, double b, Point curr, double dist) throws ArithmeticException {
        if (Double.isInfinite(a)) {
            return new Point[] { new Point(curr.x, (int)(curr.y - dist)), new Point(curr.x, (int)(curr.y + dist)) };
        }
        
        double distPow = dist * dist;
        double rest = curr.y - b;
        double aa = 1d + a * a;
        double bb = -2d * (curr.x + rest * a);
        double cc = curr.x * curr.x + rest * rest - distPow;
        
        double delta = Math.sqrt(bb * bb - 4d * aa * cc);
        double n2a = 1d / (2d * aa);
        
        double x1 = (-bb - delta) * n2a;
        int y1 = (int)(a * x1 + b);
        double x2 = (-bb + delta) * n2a;
        int y2 = (int)(a * x2 + b);
        
        return new Point[] { new Point((int)x1, y1), new Point((int)x2, y2) };
    }
    
    public static double getDistance(Point point1, Point point2) {
        return Math.sqrt(Math.pow(point1.x - point2.x, 2d) + Math.pow(point1.y - point2.y, 2d));
    }
}
